package l1j.server.server.model;

import java.text.DecimalFormat;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import l1j.opqlo.List.WeaponArmorLV;
import l1j.opqlo.List.特殊列表;
import l1j.opqlo.Server.Data.WeaponArmorLevelUp;
import l1j.server.Config;
import l1j.server.server.datatables.lock.CharItemsReading;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.Instance.L1PetInstance;
import l1j.server.server.model.item.L1ItemId;
import l1j.server.server.serverpackets.S_AddItem;
import l1j.server.server.serverpackets.S_CharVisualUpdate;
import l1j.server.server.serverpackets.S_DeleteInventoryItem;
import l1j.server.server.serverpackets.S_ItemAmount;
import l1j.server.server.serverpackets.S_ItemColor;
import l1j.server.server.serverpackets.S_ItemName;
import l1j.server.server.serverpackets.S_ItemStatus;
import l1j.server.server.serverpackets.S_OwnCharStatus;
import l1j.server.server.serverpackets.S_PacketBox;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.serverpackets.S_SystemMessage;
import l1j.server.server.templates.L1Item;
import l1j.server.server.utils.collections.Lists;

public class L1PcInventory extends L1Inventory {

	private static final long serialVersionUID = 1L;

	private static Logger _log = Logger.getLogger(L1PcInventory.class.getName());

	private static final int MAX_SIZE = 180;

	private final L1PcInstance _owner; // 所有者プレイヤー

	private int _arrowId; // 優先して使用されるアローのItemID

	private int _stingId; // 優先して使用されるスティングのItemID

	private final L1ItemInstance[] 強化轉移道具 = new L1ItemInstance[2];

	//TODO 飾品強化卷軸
	/**16777216*/
	public static final int COL_Other = 16777216;
	/**8388608*/
	public static final int COL_FIREMR = 8388608;
	/**4194304*/
	public static final int COL_WATERMR = 4194304;

	/**2097152*/
	public static final int COL_WINDMR = 2097152;

	/**1048576*/
	public static final int COL_EARTHMR = 1048576;

	/**524288*/
	public static final int COL_ADDSP = 524288;

	/**262144*/
	public static final int COL_ADDHP = 262144;

	/**131072*/
	public static final int COL_ADDMP = 131072;

	/**65536*/
	public static final int COL_HPR = 65536;

	/**32768*/
	public static final int COL_MPR = 32768;

	//TODO 飾品強化卷軸
	//TODO 魔法武器卷軸by missu0524
	/**16384*/
	public static final int COL_SKILLTYPE = 16384;

	//TODO 魔法武器卷軸by missu0524
	/**8192*/
	public static final int COL_LEVEL = 8192; //opqlo 道具升級系統

	/**4096*/
	public static final int COL_DELETE_DATE = 4096; //opqlo 道具天數刪除系統
	/**2048*/
	public static final int COL_ATTR_ENCHANT_LEVEL = 2048;
	/**1024*/
	public static final int COL_ATTR_ENCHANT_KIND = 1024;
	/**512*/
	public static final int COL_BLESS = 512;
	/**256*/
	public static final int COL_REMAINING_TIME = 256;
	/**128*/
	public static final int COL_CHARGE_COUNT = 128;
	/**64*/
	public static final int COL_ITEMID = 64;
	/**32*/
	public static final int COL_DELAY_EFFECT = 32;
	/**16*/
	public static final int COL_COUNT = 16;
	/**8*/
	public static final int COL_EQUIPPED = 8;
	/**4*/
	public static final int COL_ENCHANTLVL = 4;
	/**2*/
	public static final int COL_IS_ID = 2;
	/**1*/
	public static final int COL_DURABILITY = 1;
	private final List<L1ItemInstance>_轉換升級清單 = new ArrayList<L1ItemInstance>();
	public L1PcInventory(final L1PcInstance owner) {
		this._owner = owner;
		this._arrowId = 0;
		this._stingId = 0;
	}
	public void add轉換升級清單(final List<L1ItemInstance> list){

		if(!this._轉換升級清單.isEmpty()){
			this._轉換升級清單.clear();
		}
		this._轉換升級清單.addAll(list);
	}
	// 240段階のウェイトを算出する
	public int calcWeight240(final int weight) {
		int weight240 = 0;
		if (Config.RATE_WEIGHT_LIMIT != 0) {
			final double maxWeight = this._owner.getMaxWeight();
			if (weight > maxWeight) {
				weight240 = 240;
			} else {
				double wpTemp = weight * 100 / maxWeight * 240.00 / 100.00;
				final DecimalFormat df = new DecimalFormat("00.##");
				df.format(wpTemp);
				wpTemp = Math.round(wpTemp);
				weight240 = (int) wpTemp;
			}
		} else { // ウェイトレートが０なら重量常に０
			weight240 = 0;
		}
		return weight240;
	}
	/**傳回可以噴出的道具*/
	public List<L1ItemInstance> CaoPenalty() {//opqlo 防止噴出物品
		final List<L1ItemInstance> penaltyItems = Lists.newArrayList(); //opqlo 取得所有可噴的道具

		for(final L1ItemInstance item : this._items){
			final int itemid = item.getItemId();
			switch(itemid){
			case 255542://主城
			case 255545://\f=新手區
			case 255546://元寶掛賣區
			case 255547://一般掛賣區
			case 240131://寵物區
			case 80308://推推金幣
			case 90308: //勇者元寶
			case 245173: //拉霸代幣
			case 780013: //防噴保護卷
			case 60308: //一億支票
			case L1ItemId.ADENA://金幣
				continue;
			}
			if (item.getDeleteDate() != null) {// 道具天數刪除系統(不可存倉)
				continue;
			}
			if (!item.getItem().isTradable()) {
				continue;
			}
			if (item.getBless() >=128){
				continue;
			}
			final Object[] petlist = this._owner.getPetList().values().toArray();
			for (final Object petObject : petlist) {
				if (petObject instanceof L1PetInstance) {
					final L1PetInstance pet = (L1PetInstance) petObject;
					if (item.getId() == pet.getItemObjId()) {
						continue;
					}
				}
			}
			penaltyItems.add(item);
		}
		return penaltyItems;
	}
	@Override
	public int checkAddItem(final L1ItemInstance item, final long count) {
		return this.checkAddItem(item, count, true);
	}
	public int checkAddItem(final L1ItemInstance item, final long count, final boolean message) {
		if (item == null) {
			return -1;
		}
		final L1Item getItem = item.getItem();
		if (this.getSize() > MAX_SIZE
				|| this.getSize() == MAX_SIZE && (!item.isStackable() || !this.checkItem(getItem.getItemId()))) { // 容量確認
			if (message) {
				this.sendOverMessage(263); // \f1一人のキャラクターが持って歩けるアイテムは最大180個までです。
			}
			return SIZE_OVER;
		}
		final int itemWeight = (int) (getItem.getWeight() * count / 1000);
		//final int weight = getWeight() + item.getItem().getWeight() * count / 1000 + 1;
		final int weight = this.getWeight() + itemWeight + 1;

		if (weight < 0 || itemWeight < 0) {
			if (message) {
				this.sendOverMessage(82); // アイテムが重すぎて、これ以上持てません。
			}
			return WEIGHT_OVER;
		}
		if (this.calcWeight240(weight) >= 240) {
			if (message) {
				this.sendOverMessage(82); // アイテムが重すぎて、これ以上持てません。
			}
			return WEIGHT_OVER;
		}

		final L1ItemInstance itemExist = this.findItemId(item.getItemId());
		if (itemExist != null && itemExist.getCount() + count > MAX_AMOUNT) {
			if (message) {
				this.getOwner().sendPackets(new S_ServerMessage(166, "所持有的金幣", "超過20億。")); // \f1%0が%4%1%3%2
			}
			return AMOUNT_OVER;
		}

		return OK;
	}
	// 特定のアイテムを装備しているか確認
	public boolean checkEquipped(final int id) {
		for (final Object itemObject : this._items) {
			final L1ItemInstance item = (L1ItemInstance) itemObject;
			if (item.getItem().getItemId() == id && item.isEquipped()) {
				return true;
			}
		}
		return false;
	}
	// 特定のアイテムを全て装備しているか確認（セットボーナスがあるやつの確認用）
	public boolean checkEquipped(final int[] ids) {
		for (final int id : ids) {
			if (!this.checkEquipped(id)) {
				return false;
			}
		}
		return true;
	}
	public boolean checkItem(final L1ItemInstance item){
		return this._items.contains(item);
	}
	
//	public void CoverItem(final int type ,int[]cum , L1Inventory inv){
//
//		if(type ==1){
//			for(final int i : cum){
//				final L1ItemInstance item =	this._轉換升級清單.get(i);
//
//				if(item !=null){
//					this.tradeItem(item , 1 , inv);
//
//				}
//			}
//		}
//	}
	// ＤＢのcharacter_itemsから削除
	@Override
	public void deleteItem(final L1ItemInstance item) {
		try {
			CharItemsReading.get().deleteItem(this._owner.getId(), item);
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
		if (item.isEquipped()) {
			this.setEquipped(item, false);
		}
		if (item != null) {
			this._owner.sendPackets(new S_DeleteInventoryItem(item));
			this._items.remove(item);
			if (item.getItem().getWeight() != 0) {
				this._owner.sendPackets(new S_PacketBox(S_PacketBox.WEIGHT,this.getWeight240()));
			}
		}
	}

	/**取得身上的魔法娃娃(需求數量)**/
	public ArrayList<L1ItemInstance>getAllMagicDoll(final int size){
		final ArrayList<L1ItemInstance>list = new ArrayList<L1ItemInstance>();
		try {
			for(final L1ItemInstance item : this._items){
				if(size >0 && list.size() >= size){
					return list;
				}
				boolean isre =false;
				if(item.getItem().getUseType() == -7 ){
					for(final L1ItemInstance doll : list){
						if(doll.getItemId() == item.getItemId()){
							isre = true;
							break;
						}
					}
					if(!isre){
						list.add(item);
					}
				}
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
		return list;

	}

	public ArrayList<L1ItemInstance> getAllWeaponArmor(){

		final ArrayList<L1ItemInstance> itemList = new ArrayList<L1ItemInstance>();
		L1Item itemTable ;
		int bless ;
		WeaponArmorLV temp = null;
		for(final L1ItemInstance item: this._items){
			if(item.isEquipped()){
				continue;
			}
			itemTable = item.getItem();
			if(itemTable.getType2()!=0 ){
				bless = item.getBless();
				if (bless ==0 || bless ==128){
					temp = WeaponArmorLevelUp.getInstance().getLvUpTemp(item.getItemId());
					if(temp !=null && temp.getNextItemId() >0){
						itemList.add(item);
					}
				}
			}
		}
		this.add轉換升級清單(itemList);
		return itemList;
	}

	// 使用するアローの取得
	public L1ItemInstance getArrow() {
		return this.getBullet(0);
	}

	public ArrayList<L1ItemInstance>getBlessUpItem(){
		final ArrayList<L1ItemInstance> itemList = new ArrayList<L1ItemInstance>();
		L1Item itemTable ;
		int bless ;
		WeaponArmorLV temp = null;
		for(final L1ItemInstance item: this._items){
			if(item.isEquipped()){
				continue;
			}
			itemTable = item.getItem();
			if(itemTable.getType2()!=0 ){
				bless = item.getBless();
				if (bless ==1 || bless ==129){
					temp = WeaponArmorLevelUp.getInstance().getLvUpTemp(item.getItemId());
					if(temp !=null && temp.getBlessPrice()>0){
						itemList.add(item);
					}
				}
			}
		}
		this.add轉換升級清單(itemList);
		return itemList;
	}

	private L1ItemInstance getBullet(final int type) {
		L1ItemInstance bullet;
		int priorityId = 0;
		if (type == 0) {
			priorityId = this._arrowId; // アロー

		}else if (type == 15) {
			priorityId = this._stingId; // スティング
		}

		if (priorityId > 0){ // 優先する弾があるか

			bullet = this.findItemId(priorityId);
			if (bullet != null) {
				return bullet;
			} else{ // なくなっていた場合は優先を消す

				if (type == 0) {
					this._arrowId = 0;
				}else if (type == 15) {
					this._stingId = 0;
				}
			}
		}

		for (final Object itemObject : this._items){ // 箭矢、飛刀設置

			bullet = (L1ItemInstance) itemObject;

			if(bullet.getItem().getType2()!=0){//opqlo 修正會把裝備射出去的問題
				continue;
			}
			if(bullet.getItem().getType() != type){
				continue;
			}
			if (type == 0) {
				this._arrowId = bullet.getItem().getItemId(); // 優先にしておく
				return bullet;
			}

			if (type == 15) {
				this._stingId = bullet.getItem().getItemId(); // 優先にしておく
				return bullet;
			}

		}

		return null;
	}

	public ArrayList<L1ItemInstance> getCoverWeapon(final int type){

		final int itemtype = this.getItemType(type);
		final ArrayList<L1ItemInstance> itemList = new ArrayList<L1ItemInstance>();
		if(itemtype==0){
			return itemList;
		}

		for(final L1ItemInstance item: this._items){
			if(item.isEquipped()){
				continue;
			}
			if(item.getItem().getType1() == itemtype){
				continue;
			}
			if(item.getItem().getType2()==1 || item.getItem().getType2()==0){
				if(特殊列表.get武器轉換編號(item.getItemId() , type) >0){
					itemList.add(item);
				}
			}
		}
		this.add轉換升級清單(itemList);
		return itemList;
	}

	// 装備している特定のタイプのアイテム
	public L1ItemInstance getItemEquipped(final int type2, final int type) {
		L1ItemInstance equipeitem = null;
		for (final Object itemObject : this._items) {
			final L1ItemInstance item = (L1ItemInstance) itemObject;
			if (item.getItem().getType2() == type2
					&& item.getItem().getType() == type && item.isEquipped()) {
				equipeitem = item;
				break;
			}
		}
		return equipeitem;
	}

	private int getItemType(final int i){
		/*  sword:4, dagger:46, tohandsword:50, bow:20, blunt:11, spear:24, staff:40,
		 *  throwingknife:2922, arrow:66, gauntlet:62, claw:58, edoryu:54,
		 *  singlebow:20, singlespear:24, tohandblunt:11, tohandstaff:40,
		 *  kiringku:58, chainsword:24
		 */

		switch(i){
		case 1:
			return 4;

		case 2:
			return 50;

		case 3:
			return 20;

		case 4:
			return 40;

		case 5:
			return 54;

		case 6:
			return 24;

		case 7:
			return 58;

		case 8:
			return 62;
		}
		return 0;
	}

	public L1PcInstance getOwner() {
		return this._owner;
	}

	// 装備しているリング
	public L1ItemInstance[] getRingEquipped() {
		final L1ItemInstance equipeItem[] = new L1ItemInstance[2];
		int equipeCount = 0;
		for (final Object itemObject : this._items) {
			final L1ItemInstance item = (L1ItemInstance) itemObject;
			if (item.getItem().getType2() == 2 && item.getItem().getType() == 9
					&& item.isEquipped()) {
				equipeItem[equipeCount] = item;
				equipeCount++;
				if (equipeCount == 2) {
					break;
				}
			}
		}
		return equipeItem;
	}

	// 使用するスティングの取得
	public L1ItemInstance getSting() {
		return this.getBullet(15);
	}

	// 特定のタイプのアイテムを装備している数
	public int getTypeEquipped(final int type2, final int type) {
		int equipeCount = 0;
		for (final Object itemObject : this._items) {
			final L1ItemInstance item = (L1ItemInstance) itemObject;
			if (item.getItem().getType2() == type2
					&& item.getItem().getType() == type && item.isEquipped()) {
				equipeCount++;
			}
		}
		return equipeCount;
	}

	// 240段階のウェイトを返す
	public int getWeight240() {
		return this.calcWeight240(this.getWeight());
	}

	public int getWeight30() {
		return 0;
	}

	public L1ItemInstance[] get轉移卷軸(){
		return this.強化轉移道具;
	}

	public List<L1ItemInstance> get轉換升級清單(){
		return this._轉換升級清單;
	}

	// 装備によるＨＰ自然回復補正
	public int hpRegenPerTick() {
		int hpr = 0;
		for (final Object itemObject : this._items) {
			final L1ItemInstance item = (L1ItemInstance) itemObject;
			if (item.isEquipped()) {
				hpr += item.getItem().get_addhpr()+ item.getHpr() + item.getLvStatus().getLvHpr();//TODO 飾品強化卷軸
			}
		}
		return hpr;
	}

	// ＤＢのcharacter_itemsへ登録
	@Override
	public void insertItem(final L1ItemInstance item) {
		if (item.getCount() <= 0) {
			return;
		}
		//		item.set_char_objid(this._owner.getId());

		//opqlo 新增GM 可以交易 不能交易物品(需修改封包傳送方式)
		if(this._owner.isGm()||this._owner.isMonitor()){
			this._owner.sendPackets(new S_AddItem(item,0));
		}else{
			this._owner.sendPackets(new S_AddItem(item));
		}
		//opqlo 新增GM 可以交易 不能交易物品(需修改封包傳送方式)
		if (item.getItem().getWeight() != 0) {
			this._owner.sendPackets(new S_PacketBox(S_PacketBox.WEIGHT,this.getWeight240()));
		}

		try {
			CharItemsReading.get().storeItem(this._owner.getId(), item);
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}

	// ＤＢのcharacter_itemsの読込
	@Override
	public void loadItems() {
		try {
			final CopyOnWriteArrayList<L1ItemInstance> items = CharItemsReading.get().loadItems(this._owner.getId());

			if (items != null) {
				this._items = items;

				final List<L1ItemInstance> equipped = new CopyOnWriteArrayList<L1ItemInstance>();
				for (final L1ItemInstance item : items) {
					if (item.isEquipped()) {
						equipped.add(item);
					}
					item.setEquipped(false);
					//opqlo 道具天數刪除系統
					final Timestamp deleteDate = item.getDeleteDate();
					if (deleteDate != null) {
						final Calendar cal = Calendar.getInstance();
						final long delaytime =  (deleteDate.getTime()-cal.getTimeInMillis())/1000;
						//	final long checkDeleteDate = ((cal.getTimeInMillis() - deleteDate.getTime()) / 1000) / 3600;
						if (delaytime <= 0) {
							this.deleteItem(item);
						}
					}
					if (item.getItem().getType2() == 0
							&& item.getItem().getType() == 2) { // 照明道具
						item.setRemainingTime(item.getItem().getLightFuel());
					}
				}
				// 將已經設置為裝備的防具 重新設置為裝備狀態
				for (final L1ItemInstance item : equipped) {
					this.setEquipped(item, true, true, false);
				}
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}

	// 装備によるＭＰ自然回復補正
	public int mpRegenPerTick() {
		int mpr = 0;
		for (final Object itemObject : this._items) {
			final L1ItemInstance item = (L1ItemInstance) itemObject;
			if (item.isEquipped()) {
				mpr += item.getItem().get_addmpr()+ item.getMpr() + item.getLvStatus().getLvMpr();//TODO 飾品強化卷軸
			}
		}
		return mpr;
	}

	public void remove轉移卷軸(){
		this.強化轉移道具[0] = null;
		this.強化轉移道具[1] = null;
	}



	public void Remove轉換升級清單(){

		if(!this._轉換升級清單.isEmpty()){
			this._轉換升級清單.clear();
		}
	}

	/**
	 * インベントリ内のアイテムの状態をDBに保存する。
	 *
	 * @param item
	 *            - 更新対象のアイテム
	 * @param column
	 *            - 更新するステータスの種類
	 */
	public void saveItem(final L1ItemInstance item, int column) {
		if (column == 0) {
			return;
		}
		try {

			if(column >= COL_Other){
				CharItemsReading.get().updaOther(item);
				column -= COL_Other;
			}
			//TODO 飾品強化卷軸
			if (column >= COL_FIREMR) {
				CharItemsReading.get().updateFireMr(item);
				column -= COL_FIREMR;
			}
			if (column >= COL_WATERMR) {
				CharItemsReading.get().updateWaterMr(item);
				column -= COL_WATERMR;
			}
			if (column >= COL_WINDMR) {
				CharItemsReading.get().updateWindMr(item);
				column -= COL_WINDMR;
			}
			if (column >= COL_EARTHMR) {
				CharItemsReading.get().updateEarthMr(item);
				column -= COL_EARTHMR;
			}
			if (column >= COL_ADDSP) {
				CharItemsReading.get().updateaddSp(item);;
				column -= COL_ADDSP;
			}
			if (column >= COL_ADDHP) {
				CharItemsReading.get().updateaddHp(item);
				column -= COL_ADDHP;
			}
			if (column >= COL_ADDMP) {
				CharItemsReading.get().updateaddMp(item);
				column -= COL_ADDMP;
			}
			if (column >= COL_HPR) {
				CharItemsReading.get().updateHpr(item);
				column -= COL_HPR;
			}
			if (column >= COL_MPR) {
				CharItemsReading.get().updateMpr(item);
				column -= COL_MPR;
			}
			//TODO 飾品強化卷軸

			//TODO 魔法武器卷軸by missu0524
			if (column >= COL_SKILLTYPE) {
				CharItemsReading.get().updateSkillType(item);
				column -= COL_SKILLTYPE;
			}
			//TODO 魔法武器卷軸by missu0524

			//opqlo 道具升級系統
			if (column >= COL_LEVEL) {
				CharItemsReading.get().updateLevel(item);
				column -= COL_LEVEL;
			}
			//opqlo 道具天數刪除系統
			if (column >= COL_DELETE_DATE) {
				CharItemsReading.get().updateDeleteDate(item);
				column -= COL_DELETE_DATE;
			}
			if (column >= COL_ATTR_ENCHANT_LEVEL) { // 属性強化数
				CharItemsReading.get().updateItemAttrEnchantLevel(item);
				column -= COL_ATTR_ENCHANT_LEVEL;
			}
			if (column >= COL_ATTR_ENCHANT_KIND) { // 属性強化の種類
				CharItemsReading.get().updateItemAttrEnchantKind(item);
				column -= COL_ATTR_ENCHANT_KIND;
			}
			if (column >= COL_BLESS) { // 祝福・封印
				CharItemsReading.get().updateItemBless(item);
				column -= COL_BLESS;
			}
			if (column >= COL_REMAINING_TIME) { // 使用可能な残り時間
				CharItemsReading.get().updateItemRemainingTime(item);
				column -= COL_REMAINING_TIME;
			}

			if (column >= COL_CHARGE_COUNT) { // チャージ数
				CharItemsReading.get().updateItemChargeCount(item);
				column -= COL_CHARGE_COUNT;
			}
			if (column >= COL_ITEMID) { // 別のアイテムになる場合(便箋を開封したときなど)
				CharItemsReading.get().updateItemId(item);
				column -= COL_ITEMID;
			}
			if (column >= COL_DELAY_EFFECT) { // 効果ディレイ
				CharItemsReading.get().updateItemDelayEffect(item);
				column -= COL_DELAY_EFFECT;
			}
			if (column >= COL_COUNT) { // カウント
				CharItemsReading.get().updateItemCount(item);
				column -= COL_COUNT;
			}
			if (column >= COL_EQUIPPED) { // 装備状態
				CharItemsReading.get().updateItemEquipped(item);
				column -= COL_EQUIPPED;
			}
			if (column >= COL_ENCHANTLVL) { // エンチャント
				CharItemsReading.get().updateItemEnchantLevel(item);
				column -= COL_ENCHANTLVL;
			}
			if (column >= COL_IS_ID) { // 確認状態
				CharItemsReading.get().updateItemIdentified(item);
				column -= COL_IS_ID;
			}
			if (column >= COL_DURABILITY) { // 耐久性
				CharItemsReading.get().updateItemDurability(item);
				column -= COL_DURABILITY;
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}

	public void sendOverMessage(int message_id) {
		//TODO 釣魚中負重訊息變更by99團隊
		if (this._owner.isFishing() && message_id == 82) {
			message_id = 1518; //TODO 負重太高的狀態下無法進行釣魚。
			//TODO 釣魚中負重訊息變更by99團隊
		}
		this._owner.sendPackets(new S_ServerMessage(message_id));
	}
	// 優先するアローの設定
	public void setArrow(final int id) {
		this._arrowId = id;
	}


	// アイテムを装着脱着させる（L1ItemInstanceの変更、補正値の設定、character_itemsの更新、パケット送信まで管理）
	public void setEquipped(final L1ItemInstance item, final boolean equipped) {
		this.setEquipped(item, equipped, false, false);
	}

	public void setEquipped(final L1ItemInstance item, final boolean equipped,final boolean loaded, final boolean changeWeapon) {

		if (item.isEquipped() != equipped) { // 設定値と違う場合だけ処理
			final L1Item temp = item.getItem();
			if (equipped) { // 装着
				item.setEquipped(true);
				this._owner.getEquipSlot().set(item);

			} else { // 脱着
				if (!loaded) {
					// インビジビリティクローク バルログブラッディクローク装備中でインビジ状態の場合はインビジ状態の解除
					if (temp.getItemId() == 20077 || temp.getItemId() == 20062
							|| temp.getItemId() == 120077) {
						if (this._owner.isInvisble()) {
							this._owner.delInvis();
							return;
						}
					}
				}
				item.setEquipped(false);

				this._owner.getEquipSlot().remove(item);
			}
			if (!loaded) { // 最初の読込時はＤＢパケット関連の処理はしない
				// XXX:意味のないセッター
				this._owner.setCurrentHp(this._owner.getCurrentHp());
				this._owner.setCurrentMp(this._owner.getCurrentMp());
				this.updateItem(item, COL_EQUIPPED);
				this._owner.sendPackets(new S_OwnCharStatus(this._owner));
				if (temp.getType2() == 1 && changeWeapon == false) { // 武器の場合はビジュアル更新。ただし、武器の持ち替えで武器を脱着する時は更新しない
					this._owner.sendPacketsAll(new S_CharVisualUpdate(this._owner));
				}
				// _owner.getNetConnection().saveCharToDisk(_owner); //
				// DBにキャラクター情報を書き込む
			}
		}
	}

	// 優先するスティングの設定
	public void setSting(final int id) {
		this._stingId = id;
	}


	public void set轉移卷軸(final L1ItemInstance scroll , final L1ItemInstance item){
		this.強化轉移道具[0] = scroll;
		this.強化轉移道具[1] = item;
	}

	// 変身時に装備できない防具を外す
	private void takeoffArmor(final int polyid) {
		L1ItemInstance armor = null;

		// ヘルムからガーダーまでチェックする
		for (int type = 0; type <= 13; type++) {
			// 装備していて、装備不可の場合は外す
			if (this.getTypeEquipped(2, type) != 0
					&& !L1PolyMorph.isEquipableArmor(polyid, type)) {
				if (type == 9) { // リングの場合は、両手分外す
					armor = this.getItemEquipped(2, type);
					if (armor != null) {
						this.setEquipped(armor, false, false, false);
					}
					armor = this.getItemEquipped(2, type);
					if (armor != null) {
						this.setEquipped(armor, false, false, false);
					}
				} else {
					armor = this.getItemEquipped(2, type);
					if (armor != null) {
						this.setEquipped(armor, false, false, false);
					}
				}
			}
		}
	}

	// 変身時に装備できない装備を外す
	public void takeoffEquip(final int polyid) {
		this.takeoffWeapon(polyid);
		this.takeoffArmor(polyid);
	}

	// 変身時に装備できない武器を外す
	private void takeoffWeapon(final int polyid) {
		if (this._owner.getWeapon() == null) { // 素手
			return;
		}

		boolean takeoff = false;
		final int weapon_type = this._owner.getWeapon().getItem().getType();
		// 装備出来ない武器を装備してるか？
		takeoff = !L1PolyMorph.isEquipableWeapon(polyid, weapon_type);
		if (takeoff) {
			this.setEquipped(this._owner.getWeapon(), false, false, false);
		}
	}

	@Override
	public void updateItem(final L1ItemInstance item) {
		this.updateItem(item, COL_COUNT);
		if (item.getItem().isToBeSavedAtOnce()) {
			this.saveItem(item, COL_COUNT);
		}
	}

	/**
	 * インベントリ内のアイテムの状態を更新する。
	 *
	 * @param item
	 *            - 更新対象のアイテム
	 * @param column
	 *            - 更新するステータスの種類
	 */
	@Override
	public void updateItem(final L1ItemInstance item, int column) {
		if(column <=0){return;}

		if(column >= COL_Other){
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_Other;
		}

		//TODO 飾品強化卷軸
		if (column >= COL_FIREMR) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_FIREMR;
		}
		if (column >= COL_WATERMR) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_WATERMR;
		}
		if (column >= COL_WINDMR) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_WINDMR;
		}
		if (column >= COL_EARTHMR) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_EARTHMR;
		}
		if (column >= COL_ADDSP) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_ADDSP;
		}
		if (column >= COL_ADDHP) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_ADDHP;
		}
		if (column >= COL_ADDMP) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_ADDMP;
		}
		if (column >= COL_HPR) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_HPR;
		}
		if (column >= COL_MPR) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_MPR;
		}
		//TODO 飾品強化卷軸

		//TODO 魔法武器卷軸by missu0524
		if (column >= COL_SKILLTYPE) {
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_SKILLTYPE;
			//TODO 魔法武器卷軸by missu0524
		}
		if (column >= COL_LEVEL){//opqlo 道具升級系統
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_LEVEL;
		}
		if (column >= COL_ATTR_ENCHANT_LEVEL) { // 属性強化数
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_ATTR_ENCHANT_LEVEL;
		}
		if (column >= COL_ATTR_ENCHANT_KIND) { // 属性強化の種類
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_ATTR_ENCHANT_KIND;
		}
		if (column >= COL_BLESS) { // 祝福・封印
			this._owner.sendPackets(new S_ItemColor(item));
			column -= COL_BLESS;
		}
		if (column >= COL_REMAINING_TIME) { // 使用可能な残り時間
			this._owner.sendPackets(new S_ItemName(item));
			column -= COL_REMAINING_TIME;
		}

		if (column >= COL_CHARGE_COUNT) { // チャージ数
			this._owner.sendPackets(new S_ItemName(item));
			column -= COL_CHARGE_COUNT;
		}
		if (column >= COL_ITEMID) { // 別のアイテムになる場合(便箋を開封したときなど)
			this._owner.sendPackets(new S_ItemStatus(item));
			this._owner.sendPackets(new S_ItemColor(item));
			this._owner.sendPackets(new S_PacketBox(S_PacketBox.WEIGHT,this.getWeight240()));
			column -= COL_ITEMID;
		}
		if (column >= COL_DELAY_EFFECT) { // 効果ディレイ
			column -= COL_DELAY_EFFECT;
		}
		if (column >= COL_COUNT) { // カウント
			this._owner.sendPackets(new S_ItemAmount(item));

			final int weight = item.getWeight();
			if (weight != item.getLastWeight()) {
				item.setLastWeight(weight);
				this._owner.sendPackets(new S_ItemStatus(item));
			} else {
				this._owner.sendPackets(new S_ItemName(item));
			}
			if (item.getItem().getWeight() != 0) {
				// XXX 240段階のウェイトが変化しない場合は送らなくてよい
				this._owner.sendPackets(new S_PacketBox(S_PacketBox.WEIGHT,
						this.getWeight240()));
			}
			column -= COL_COUNT;
		}
		if (column >= COL_EQUIPPED) { // 装備状態
			this._owner.sendPackets(new S_ItemName(item));
			column -= COL_EQUIPPED;
		}
		if (column >= COL_ENCHANTLVL) { // エンチャント
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_ENCHANTLVL;
		}
		if (column >= COL_IS_ID) { // 確認状態
			this._owner.sendPackets(new S_ItemStatus(item));
			this._owner.sendPackets(new S_ItemColor(item));
			column -= COL_IS_ID;
		}
		if (column >= COL_DURABILITY) { // 耐久性
			this._owner.sendPackets(new S_ItemStatus(item));
			column -= COL_DURABILITY;
		}
	}

	/**檢查身上有無到期物品須刪除**/
	public void isHaveDeleteItem(){
		for(final L1ItemInstance item : _items){
			final Timestamp deleteDate = item.getDeleteDate();
			if (deleteDate != null) {
				final Calendar cal = Calendar.getInstance();
				final long checkDeleteDate = (cal.getTimeInMillis() - deleteDate.getTime()) / 1000;
				if (checkDeleteDate >= 0) {
					this.removeItem(item);
					_owner.sendPackets(new S_SystemMessage("\\aE"+ item.getLogName() + " 時間到期，已被系統回收。"));
				}
			}
		}
	}


	/**
	 * 取回可供強化並已裝備的武器裝備
	 * 1:helm, 2:armor, 3:T, 4:cloak, 5:glove, 6:boots, 
	 * 7:shield, 8:amulet, 9:ring, 10:belt, 11:ring2, 
	 * 12:earring, 13:guarder, 14:runeword_left, 
	 * 15:runeword_right, 16:runeword_middle, 
	 * 17:runeword_l_d, 18:runeword_r_d*/

	public HashMap<Integer , L1ItemInstance> getEquippedItem(){
		final HashMap<Integer , L1ItemInstance >map = new HashMap<Integer , L1ItemInstance>();
		for(final L1ItemInstance item : _items){
			if(item.isEquipped()){
				final L1Item temp = item.getItem();
				if(temp.getType2() ==2){
					final int type = temp.getType();
					switch(type){
					case 1: case 2: case 3: case 4:
					case 5: case 6: case 7: case 10:
						if(temp.get_safeenchant()>=0){
							map.put(type, item);
						}
						break;
					case 13:
						if(temp.get_safeenchant()>=0){
							map.put(7, item);
						}
						break;
					}
				}
			}
		}
		map.put(0, _owner.getWeapon());
		return map;
	}
	
	public L1ItemInstance getEquippedItem(final int type2, final int type) {
		for (final Object itemObject : this._items) {
			final L1ItemInstance item = (L1ItemInstance) itemObject;
			if (item.getItem().getType2() == type2
					&& item.getItem().getType() == type && item.isEquipped()) {
				return item;
			}
		}
		return null;
	}
}
